package com.lineage.server.datatables;

import com.lineage.DatabaseFactory;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.RandomArrayList;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Drop_limit {
  private static Logger _log;
  
  private static Log _log1;
  
  private static Drop_limit _instance;
  
  public static HashMap<Integer, Drop_limit> _itemIdIndex;
  
  private int _itemId;
  
  private int _totalCount;
  
  private int _appearCount;
  
  private Calendar _next_drop_time;
  
  private int _drop_interval_min;
  
  private int _drop_interval_max;
  
  private static final Map<Integer, Drop_limit> _mons = new HashMap<>();
  
  static {
    _log = Logger.getLogger(Drop_limit.class.getName());
    _log1 = LogFactory.getLog(Drop_limit.class);
    _itemIdIndex = new HashMap<>();
  }
  
  public static Drop_limit get() {
    if (_instance == null)
      _instance = new Drop_limit(); 
    return _instance;
  }
  
  public static void reload() {
    _itemIdIndex.clear();
    _instance = null;
    get();
  }
  
  private Drop_limit() {
    loadChackDrop();
  }
  
  private static void loadChackDrop() {
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT * FROM w_物品掉落限制三");
      rs = pstm.executeQuery();
      fillChackDrop(rs);
    } catch (SQLException e) {
      _log.log(Level.SEVERE, "error while creating w_物品掉落限制三 table", e);
      return;
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    SQLUtil.close(rs);
    SQLUtil.close(pstm);
    SQLUtil.close(con);
  }
  
  private static Calendar timestampToCalendar(Timestamp ts) {
    Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(ts.getTime());
    return cal;
  }
  
  private static void fillChackDrop(ResultSet rs) throws SQLException {
    PerformanceTimer timer = new PerformanceTimer();
    while (rs.next()) {
      int itemId = rs.getInt("物品ID");
      int totalCount = rs.getInt("限制总数");
      int appearCount = rs.getInt("掉出数量");
      Timestamp time = rs.getTimestamp("最后掉落时间");
      int drop_interval_min = rs.getInt("最小时间后");
      int drop_interval_max = rs.getInt("最大时间内");
      if (drop_interval_max < drop_interval_min)
        drop_interval_max = drop_interval_min; 
      Calendar next_drop_time = null;
      if (time != null)
        next_drop_time = timestampToCalendar(rs.getTimestamp("最后掉落时间")); 
      Drop_limit armor_upgrade = new Drop_limit(itemId, totalCount, appearCount, next_drop_time, drop_interval_min, drop_interval_max);
      _itemIdIndex.put(Integer.valueOf(itemId), armor_upgrade);
    } 
    _log1.info("载入掉宝限制: " + _itemIdIndex.size() + "(" + timer.get() + "ms)");
  }
  
  public Drop_limit getTemplate(int itemId) {
    return _itemIdIndex.get(Integer.valueOf(itemId));
  }
  
  public Drop_limit[] getDissolveList() {
    return (Drop_limit[])_itemIdIndex.values().toArray((Object[])new Drop_limit[_itemIdIndex.size()]);
  }
  
  public boolean checkItemIdCanDrop(int itemId) {
    Drop_limit limit = get().getTemplate(itemId);
    if (limit == null)
      return true; 
    if (limit.get_totalCount() <= limit.get_appearCount())
      return false; 
    if (limit.get_next_drop_time() != null) {
      Calendar cals = Calendar.getInstance();
      long nowTime = System.currentTimeMillis();
      cals.setTimeInMillis(nowTime);
      return cals.after(limit.get_next_drop_time());
    } 
    return true;
  }
  
  public void addCount(int itemId, long l) {
    Drop_limit limit = get().getTemplate(itemId);
    if (limit != null) {
      limit.add_appearCount(l);
      Calendar cals = null;
      if (limit.get_next_drop_time() != null) {
        int time = limit.get_drop_interval_min() + RandomArrayList.getInt(limit.get_drop_interval_max() - limit.get_drop_interval_min());
        long newTime = (time * 60 * 1000);
        cals = Calendar.getInstance();
        cals.setTimeInMillis(System.currentTimeMillis() + newTime);
        limit.get_next_drop_time().setTimeInMillis(cals.getTimeInMillis());
      } else if (limit.get_drop_interval_min() != 0) {
        int time = limit.get_drop_interval_min() + RandomArrayList.getInt(limit.get_drop_interval_max() - limit.get_drop_interval_min());
        long newTime = (time * 60 * 1000);
        cals = Calendar.getInstance();
        cals.setTimeInMillis(System.currentTimeMillis() + newTime);
        limit.get_next_drop_time().setTimeInMillis(cals.getTimeInMillis());
      } 
      limit.upDateNextSpawnTime(itemId, cals, limit.get_appearCount());
    } 
  }
  
  public void upDateNextSpawnTime(int itemId, Calendar spawnTime, int count) {
    Connection con = null;
    PreparedStatement pstm = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("UPDATE `w_物品掉落限制三` SET `最后掉落时间`=?, `掉出数量`=? WHERE `物品ID`=?");
      String fm = null;
      if (spawnTime != null) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        fm = sdf.format(spawnTime.getTime());
      } 
      int i = 0;
      pstm.setString(++i, fm);
      pstm.setInt(++i, count);
      pstm.setInt(++i, itemId);
      pstm.execute();
    } catch (Exception e) {
      _log1.error(e.getLocalizedMessage(), e);
      return;
    } finally {
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    SQLUtil.close(pstm);
    SQLUtil.close(con);
  }
  
  public Drop_limit(int itemId, int totalCount, int appearCount, Calendar next_drop_time, int drop_interval_min, int drop_interval_max) {
    this._itemId = itemId;
    this._totalCount = totalCount;
    this._appearCount = appearCount;
    this._next_drop_time = next_drop_time;
    this._drop_interval_min = drop_interval_min;
    this._drop_interval_max = drop_interval_max;
  }
  
  public int get_itemId() {
    return this._itemId;
  }
  
  public int get_totalCount() {
    return this._totalCount;
  }
  
  public int get_appearCount() {
    return this._appearCount;
  }
  
  public void add_appearCount(long l) {
    this._appearCount = (int)(this._appearCount + l);
  }
  
  public Calendar get_next_drop_time() {
    return this._next_drop_time;
  }
  
  public void set_next_drop_time(Calendar i) {
    this._next_drop_time = i;
  }
  
  public static int CheckNpcMid(int Npc_Mid) {
    Drop_limit mon = get().getMon(Npc_Mid);
    if (mon == null)
      return 0; 
    int npcmid = mon._itemId;
    return npcmid;
  }
  
  public int get_drop_interval_min() {
    return this._drop_interval_min;
  }
  
  public int get_drop_interval_max() {
    return this._drop_interval_max;
  }
  
  public Drop_limit getMon(int Item_Id) {
    return _mons.get(Integer.valueOf(Item_Id));
  }
}
